package serveur;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ConcurrentHashMap;

public class Serveur  implements Serializable {

   //********************** DEBUT MAIN ***************************//
	public static void main(String[] args){
		try{
                    Serveur serveur = new Serveur(3000).restaure();
                    serveur.setPort(3000);
                    serveur.traites = new ConcurrentHashMap<Integer,TraitementClient>();
                    //serveur.initialisationSalons();
                    
                    System.out.println("Salons : ");
                    for(String key : serveur.salons.keySet()){
                       System.out.println(serveur.salons.get(key).getTitre());
                    }   
                    System.out.println("Utilisateurs : ");
                    for(String key : serveur.utilisateurs.keySet()){
                       System.out.println(serveur.utilisateurs.get(key).getPseudo());
                       for(String key1 : serveur.utilisateurs.get(key).getContacts().keySet()){
                             System.out.println("     -"+serveur.utilisateurs.get(key).getContacts().get(key1).getPseudo());
                    }
                    }
                
                    try{serveur.socketEcoute = new ServerSocket(serveur.getPort());}catch(Exception e){}//socket d'écoute sur le port indiqué
                    System.out.println("Serveur en marche sur le port : " + serveur.getPort() );
                    
                    int i=1;
                    while(true){
                            TraitementClient t = new TraitementClient(serveur.attenteConnexionTCP(),serveur);//Attente de la connexion d'un client qui va instancier une Socket (socket de transfert)
                            serveur.traites.put(i,t);
                            serveur.traites.get(i).start();
                            i++;
                    }
		}
		catch(UnknownHostException e){
			System.out.println("Le numero de port donné au serveur est déja pris par un autre serveur qui tourne déja");
		}
	}
	//********************** FIN MAIN ***************************//
	

	// Attributs 
		private transient int port;//numero de port du serveur
		public transient ServerSocket socketEcoute;//socket d'écoute sur un port (permet l'attente de la connexion d'un client)
                public transient  ConcurrentHashMap<Integer,TraitementClient> traites;
                public ConcurrentHashMap<String,Salon> salons;
                public ConcurrentHashMap<String,Utilisateur> utilisateurs;
	// Constructeur
		public Serveur(int port){
			 this.setPort(port);
                         traites = new ConcurrentHashMap<Integer,TraitementClient>();
                         salons = new  ConcurrentHashMap<String,Salon>();
                         utilisateurs = new  ConcurrentHashMap<String,Utilisateur>();
		}
            
         //AjouterUtilisateur
                public void ajouterUtilisateur(String pseudo, Utilisateur u){
                    this.utilisateurs.put(pseudo, u);
                    this.sauve();
                }
         //AjouerSalon
                public void ajouterSalon(String titre, Salon s){
                    this.salons.put(titre, s);
                    this.sauve();
                }
	
	//Attente de connexion d'un client
		public Socket attenteConnexionTCP()throws UnknownHostException{
			try{
			      Socket sok  =  socketEcoute.accept();//Attendre d'un client  qui va crée une (Socket) socketTransfert (Bloquant) (attribue une @ip et un num de port)
                              return sok;
                        }
			catch(UnknownHostException e){
				 throw new UnknownHostException();
			}
			catch(Exception e){
				  System.out.println("Exception levée dans l'attente de connexion 'Serveur' : " + e.toString());
			 }
			return null;
		}
	
	//Accesseurs & Mutateurs
		public int getPort() {
			return port;
		}

		private void setPort(int port) {
			this.port = port;
		}
         // ************************************************************************************************************
        // Opérations liées à la sérialisation des objets 
        // ************************************************************************************************************

                //restauration des objets de l'application
                public Serveur restaure() {
                    try {
                        FileInputStream fichier = new FileInputStream("FsauvServeur.ser");
                        ObjectInputStream in = new ObjectInputStream(fichier);
                        return((Serveur) in.readObject());
                    } catch (Exception e) {
                        System.out.println("Probléme de restauration du fichier : " + e.getMessage() + "  " + e.toString());
                        return this;
                    } 
                }

                // sauvegarde des objets de l'application
                public void sauve() {
                    try {
                            FileOutputStream f = new FileOutputStream("FsauvServeur.ser");
                            ObjectOutputStream out = new ObjectOutputStream(f);
                            out.writeObject(this);
                    } catch (Exception e) {
                            System.out.println("Probléme de sauvgarde dans le fichier : " + e.getMessage() + "  " + e.toString());
                    }
                }
                //Initialisation de notre base 
                public void initialisationSalons(){
                    Salon informatique = new Salon("Informatique","");
                    Salon economie = new Salon("Economie","");
                    Salon mathematique = new Salon("Mathematique","");
                    
                    Utilisateur u1 = new Utilisateur("samir","","","","mdpsamir");
                    Utilisateur u2 = new Utilisateur("colin","","","","mdpcolin");
                    Utilisateur u3 = new Utilisateur("xxx","","","","mdpxxx");

                    this.ajouterSalon(informatique.getTitre(),informatique);
                    this.ajouterSalon(economie.getTitre(),economie);
                    this.ajouterSalon(mathematique.getTitre(),mathematique);
                    
                    this.ajouterUtilisateur(u1.getPseudo(), u1);
                    this.ajouterUtilisateur(u2.getPseudo(), u2);
                    u1.ajouterContact(u2.getPseudo(), u2);
                    u2.ajouterContact(u2.getPseudo(), u1);
                }           
} // Fin de la classe Serveur 
